package com.company.cloud.article.modules.mgr.service.impl;

import java.time.LocalDateTime;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

import javax.annotation.Resource;

import cn.hutool.system.UserInfo;
import com.company.cloud.article.modules.mgr.controller.req.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.company.cloud.article.modules.cache.models.ArticleModel;
import com.company.cloud.article.modules.base.entity.ArticleCategoryMappingInfo;
import com.company.cloud.article.modules.base.entity.ArticleCompanyRelInfo;
import com.company.cloud.article.modules.base.entity.ArticleInfo;
import com.company.cloud.article.modules.base.service.ArticleCategoryMappingInfoService;
import com.company.cloud.article.modules.base.service.ArticleCompanyRelInfoService;
import com.company.cloud.article.modules.base.service.ArticleInfoService;
import com.company.cloud.article.modules.cache.utils.ArticleCacheKeys;
import com.company.cloud.article.modules.cache.utils.ArticleConvertUtils;
import com.company.cloud.article.modules.mgr.mapper.ArticleMgrMapper;
import com.company.cloud.article.modules.mgr.service.ArticleMgrService;
import com.company.cloud.common.asserts.ValidatorUtils;
import com.company.cloud.common.bean.LoginSimpleUserInfo;
import com.company.cloud.common.constant.BaseConstant;
import com.company.cloud.common.constant.BaseConstant.EnabledEnum;
import com.company.cloud.common.constant.BaseConstant.YNEnum;
import com.company.cloud.common.constant.BaseReturnEnum;
import com.company.cloud.common.exception.BusinessException;
import com.company.cloud.common.utils.StrSplitUtils;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service
public class ArticleMgrServiceImpl implements ArticleMgrService {

	@Autowired
	private ArticleInfoService articleInfoService;
	@Autowired
	private ArticleCompanyRelInfoService articleCompanyRelInfoService;
	@Autowired
	private ArticleCategoryMappingInfoService articleCategoryMappingInfoService;
	@Resource
	private ArticleMgrMapper articleMgrMapper;

	@Transactional
	@Override
	public void save(ArticleMgrSaveParam params, LoginSimpleUserInfo userInfo) {
		ValidatorUtils.validate(params);
		ArticleInfo entity = new ArticleInfo();
		entity.setArticleNo(ArticleCacheKeys.getArticleId());
		entity.setCompanyNo(params.getCompanyNo());
		entity.setTitle(params.getTitle());
		entity.setContent(params.getContent());
		entity.setSummary(params.getSummary());

		entity.setTitleEn(params.getTitleEn());
		entity.setContentEn(params.getContentEn());
		entity.setSummaryEn(params.getSummaryEn());

		entity.setThumbnail(StrSplitUtils.list2string(params.getThumbnail()));
		entity.setStyle(params.getStyle());
		entity.setCommentStatus(params.getCommentStatus());
		entity.setMetaKeywords(params.getMetaKeywords());
		entity.setMetaDescription(params.getMetaDescription());
		entity.setIsPubPlatform(params.getIsPubPlatform());
		entity.setTags(StrSplitUtils.list2string_prefix(params.getTags()));
		entity.addCreateParam(userInfo);
		entity.addEditParam(userInfo);
		articleInfoService.save(entity);

		ArticleCompanyRelInfo articleRel = new ArticleCompanyRelInfo();
		articleRel.setArticleRelNo(ArticleCacheKeys.getArticleCompanyRelId());
		articleRel.setArticleNo(entity.getArticleNo());
		articleRel.setCompanyNo(params.getCompanyNo());
		articleRel.setOrders(params.getOrders());
		articleRel.setTags(StrSplitUtils.list2string_prefix(params.getTags()));
		articleRel.setRemarks(params.getRemarks());
		articleRel.setIsTop(params.getIsTop());
		articleRel.setCommentCount(0);
		articleRel.setCommentTime(LocalDateTime.now());
		articleRel.setViewCount(0);
		articleRel.setIsRel(YNEnum.NO.getCode());
		articleRel.setShowChannel(StrSplitUtils.list2string_prefix(params.getShowChannel()));
		articleRel.setState(params.getState());
		articleRel.addCreateParam(userInfo);
		articleRel.addEditParam(userInfo);
		articleCompanyRelInfoService.save(articleRel);

		if (!CollectionUtils.isEmpty(params.getCategoryIds())) {
			List<ArticleCategoryMappingInfo> categoryList = new ArrayList<ArticleCategoryMappingInfo>();
			params.getCategoryIds().forEach(id -> {
				ArticleCategoryMappingInfo categoryEntity = new ArticleCategoryMappingInfo();
				categoryEntity.setCompanyNo(articleRel.getCompanyNo());
				categoryEntity.setArticleNo(articleRel.getArticleNo());
				categoryEntity.setArticleRelNo(articleRel.getArticleRelNo());
				categoryEntity.setCategoryId(id);
				categoryEntity.addCreateParam(userInfo);
				categoryEntity.addEditParam(userInfo);
				categoryList.add(categoryEntity);
			});
			articleCategoryMappingInfoService.saveBatch(categoryList);
		}
	}

	@Transactional
	@Override
	public void update(ArticleMgrUpdateParam params, LoginSimpleUserInfo userInfo) {
		ValidatorUtils.validate(params);
		ArticleInfo entity = articleInfoService.getById(params.getArticleNo());
		if (entity == null || EnabledEnum.DISABLED.getCode().equals(entity.getRowsState())) {
			throw new BusinessException(BaseReturnEnum.DATA_NOT_EXISTS);
		}


		ArticleCompanyRelInfo articleRel = articleCompanyRelInfoService.getOne(
				new QueryWrapper<ArticleCompanyRelInfo>()
						.eq("article_no", params.getArticleNo())
						.eq("company_no", params.getCompanyNo())
						.eq("is_rel", YNEnum.NO.getCode())
		);

		if (articleRel == null) {
			throw new BusinessException("只能修改自己发布的资讯");
		}
		entity.setCompanyNo(params.getCompanyNo());
		entity.setTitle(params.getTitle());
		entity.setContent(params.getContent());
		entity.setSummary(params.getSummary());

		entity.setTitleEn(params.getTitleEn());
		entity.setContentEn(params.getContentEn());
		entity.setSummaryEn(params.getSummaryEn());

		entity.setThumbnail(StrSplitUtils.list2string(params.getThumbnail()));
		entity.setStyle(params.getStyle());
		entity.setCommentStatus(params.getCommentStatus());
		entity.setMetaKeywords(params.getMetaKeywords());
		entity.setMetaDescription(params.getMetaDescription());
		entity.setIsPubPlatform(params.getIsPubPlatform());
		entity.setTags(StrSplitUtils.list2string_prefix(params.getTags()));
		entity.addEditParam(userInfo);
		articleInfoService.updateById(entity);

		articleRel.setCompanyNo(params.getCompanyNo());
		articleRel.setOrders(params.getOrders());
		articleRel.setTags(StrSplitUtils.list2string_prefix(params.getTags()));
		articleRel.setRemarks(params.getRemarks());
		articleRel.setIsTop(params.getIsTop());
		articleRel.setShowChannel(StrSplitUtils.list2string_prefix(params.getShowChannel()));
		articleRel.setState(params.getState());
		articleRel.addEditParam(userInfo);
		articleCompanyRelInfoService.updateById(articleRel);

		if (!CollectionUtils.isEmpty(params.getCategoryIds())) {
			List<ArticleCategoryMappingInfo> categoryList = new ArrayList<ArticleCategoryMappingInfo>();
			params.getCategoryIds().forEach(id -> {
				ArticleCategoryMappingInfo categoryEntity = new ArticleCategoryMappingInfo();
				categoryEntity.setCompanyNo(articleRel.getCompanyNo());
				categoryEntity.setArticleNo(articleRel.getArticleNo());
				categoryEntity.setArticleRelNo(articleRel.getArticleRelNo());
				categoryEntity.setCategoryId(id);
				categoryEntity.addCreateParam(userInfo);
				categoryEntity.addEditParam(userInfo);
				categoryList.add(categoryEntity);
			});
			articleCategoryMappingInfoService.remove(new QueryWrapper<ArticleCategoryMappingInfo>()
					.eq("article_no", entity.getArticleNo()));
			articleCategoryMappingInfoService.saveBatch(categoryList);
		}

	}


	@Transactional
	@Override
	public void remove(String articleNo, LoginSimpleUserInfo userInfo) {
		ArticleInfo entity = articleInfoService.getById(articleNo);
		if (entity == null || EnabledEnum.DISABLED.getCode().equals(entity.getRowsState())) {
			throw new BusinessException(BaseReturnEnum.DATA_NOT_EXISTS);
		}
		entity.setRowsState(EnabledEnum.DISABLED.getCode());
		entity.addEditParam(userInfo);
		articleInfoService.updateById(entity);
	}

	/**资讯上下架*/
	@Override
	public void updateState(ArticleMgrUpdateStateParam params, LoginSimpleUserInfo userInfo) {
		ValidatorUtils.validate(params);
		ArticleCompanyRelInfo articleRel = articleCompanyRelInfoService.getOne(
				new QueryWrapper<ArticleCompanyRelInfo>()
						.eq("article_no", params.getArticleNo())
						.eq("company_no", userInfo.getCompanyNo())
		);
		if(articleRel==null){
			throw new BusinessException(BaseReturnEnum.DATA_NOT_EXISTS);
		}
		if(!params.getState().equals(articleRel.getState())){
			articleRel.setState(params.getState());
			articleRel.addEditParam(userInfo);
			articleCompanyRelInfoService.updateById(articleRel);
		}
	}

	/**资讯批量上下架*/
	@Override
	public void updateStateBatch(ArticleMgrUpdateStateBatchParam params, LoginSimpleUserInfo userInfo){
		ValidatorUtils.validate(params);
		List<ArticleCompanyRelInfo> articleRelList = articleCompanyRelInfoService.list(
				new QueryWrapper<ArticleCompanyRelInfo>()
						.in("article_no", params.getArticleNo())
						.eq("company_no", userInfo.getCompanyNo())
		);

		if(CollectionUtils.isEmpty(articleRelList)){
			throw new BusinessException(BaseReturnEnum.DATA_NOT_EXISTS);
		}

		List<ArticleCompanyRelInfo> updateArticleRelList =new ArrayList<>();
		for(ArticleCompanyRelInfo articleRel:articleRelList){
			if(!params.getState().equals(articleRel.getState())){
				articleRel.setState(params.getState());
				articleRel.addEditParam(userInfo);
				updateArticleRelList.add(articleRel);
			}
		}

		if(updateArticleRelList.size()>0){
			articleCompanyRelInfoService.updateBatchById(updateArticleRelList);
		}

	}


	//---------------------------资讯引用---------------------------------------

	/**新增引用*/
	@Override
	public void addRel(ArticleRelAddParam params, LoginSimpleUserInfo userInfo) {
		ValidatorUtils.validate(params);
		ArticleInfo entity = articleInfoService.getById(params.getArticleNo());
		if (entity == null || EnabledEnum.DISABLED.getCode().equals(entity.getRowsState())) {
			throw new BusinessException(BaseReturnEnum.DATA_NOT_EXISTS);
		}
		if (!YNEnum.YES.getCode().equals(entity.getIsPubPlatform())) {
			throw new BusinessException("未发布到平台");
		}
		ArticleCompanyRelInfo articleRelEntity = articleCompanyRelInfoService.getOne(
				new QueryWrapper<ArticleCompanyRelInfo>()
						.eq("article_no", params.getArticleNo())
						.eq("company_no", userInfo.getCompanyNo())
						.eq("rows_state", EnabledEnum.ENABLED.getCode())
		);

		if (articleRelEntity != null) {
			throw new BusinessException(BaseReturnEnum.DATA_EXISTS);
		}
		ArticleCompanyRelInfo articleRel = new ArticleCompanyRelInfo();
		articleRel.setArticleRelNo(ArticleCacheKeys.getArticleCompanyRelId());
		articleRel.setArticleNo(entity.getArticleNo());
		articleRel.setCompanyNo(userInfo.getCompanyNo());
		articleRel.setOrders(params.getOrders());
		articleRel.setTags(StrSplitUtils.list2string_prefix(params.getTags()));
		articleRel.setShowChannel(StrSplitUtils.list2string_prefix(params.getShowChannel()));
		articleRel.setRemarks(params.getRemarks());
		articleRel.setCommentCount(0);
		articleRel.setCommentTime(LocalDateTime.now());
		articleRel.setViewCount(0);
		articleRel.setIsRel(YNEnum.YES.getCode());
		articleRel.setState(params.getState());
		articleRel.setIsTop(params.getIsTop());
		articleRel.addCreateParam(userInfo);
		articleRel.addEditParam(userInfo);
		articleCompanyRelInfoService.save(articleRel);

		if (!CollectionUtils.isEmpty(params.getCategoryIds())) {
			List<ArticleCategoryMappingInfo> categoryList = new ArrayList<ArticleCategoryMappingInfo>();
			params.getCategoryIds().forEach(id -> {
				ArticleCategoryMappingInfo categoryEntity = new ArticleCategoryMappingInfo();
				categoryEntity.setCompanyNo(articleRel.getCompanyNo());
				categoryEntity.setArticleNo(articleRel.getArticleNo());
				categoryEntity.setArticleRelNo(articleRel.getArticleRelNo());
				categoryEntity.setCategoryId(id);
				categoryEntity.addCreateParam(userInfo);
				categoryEntity.addEditParam(userInfo);
				categoryList.add(categoryEntity);
			});
			articleCategoryMappingInfoService.saveBatch(categoryList);
		}
	}


	/**批量新增引用*/
	@Override
	public void addRel(ArticleRelAddListParam params, LoginSimpleUserInfo userInfo) {
		ValidatorUtils.validate(params);
		ArticleInfo entity = articleInfoService.getById(params.getArticleNo());
		if (entity == null || EnabledEnum.DISABLED.getCode().equals(entity.getRowsState())) {
			throw new BusinessException(BaseReturnEnum.DATA_NOT_EXISTS);
		}
		if (!YNEnum.YES.getCode().equals(entity.getIsPubPlatform())) {
			throw new BusinessException("");
		}
		//todo:
	}

	/***/
	@Override
	public void removeRel(String articleRelNo, LoginSimpleUserInfo userInfo) {
		ArticleCompanyRelInfo articleRel = articleCompanyRelInfoService.getById(articleRelNo);
		if (articleRel == null || EnabledEnum.DISABLED.getCode().equals(articleRel.getRowsState())) {
			throw new BusinessException(BaseReturnEnum.DATA_NOT_EXISTS);
		}
		articleRel.setRowsState(EnabledEnum.DISABLED.getCode());
		articleRel.addEditParam(userInfo);
		articleCompanyRelInfoService.updateById(articleRel);
	}

	/***/
	@Override
	public void updateRel(ArticleRelUpdateParam params, LoginSimpleUserInfo userInfo) {
		ArticleCompanyRelInfo articleRel = articleCompanyRelInfoService.getById(params.getArticleRelNo());
		if (articleRel == null || EnabledEnum.DISABLED.getCode().equals(articleRel.getRowsState())) {
			throw new BusinessException(BaseReturnEnum.DATA_NOT_EXISTS);
		}
		articleRel.setOrders(params.getOrders());
		articleRel.setTags(StrSplitUtils.list2string_prefix(params.getTags()));
		articleRel.setShowChannel(StrSplitUtils.list2string_prefix(params.getShowChannel()));
		articleRel.setRemarks(params.getRemarks());
		articleRel.setState(params.getState());
		articleRel.setIsTop(params.getIsTop());
		articleRel.addEditParam(userInfo);
		articleCompanyRelInfoService.updateById(articleRel);
	}

	/***/
	@Override
	public void updateRelState(ArticleRelUpdateStateParam params, LoginSimpleUserInfo userInfo) {
		ValidatorUtils.validate(params);
		ArticleCompanyRelInfo articleRel = articleCompanyRelInfoService.getById(params.getArticleRelNo());
		if (articleRel == null || EnabledEnum.DISABLED.getCode().equals(articleRel.getRowsState())) {
			throw new BusinessException(BaseReturnEnum.DATA_NOT_EXISTS);
		}
		if(!articleRel.getState().equals(params.getState())){
			articleRel.setState(params.getState());
			articleRel.addEditParam(userInfo);
			articleCompanyRelInfoService.updateById(articleRel);
		}
	}

	/***/
	@Override
	public void updateRelStateBatch(ArticleRelUpdateStateBatchParam params, LoginSimpleUserInfo userInfo) {
		ValidatorUtils.validate(params);
		List<ArticleCompanyRelInfo> articleRelList = articleCompanyRelInfoService.list(
				new QueryWrapper<ArticleCompanyRelInfo>()
				.in("article_rel_no",params.getArticleRelNo())
				.eq("rows_state",EnabledEnum.ENABLED.getCode())
		);

		if(CollectionUtils.isEmpty(articleRelList)){
			throw new BusinessException(BaseReturnEnum.DATA_NOT_EXISTS);
		}
		List<ArticleCompanyRelInfo> updateArticleRelList =new ArrayList<>();
		for(ArticleCompanyRelInfo articleRel : articleRelList){
			if(!articleRel.getState().equals(params.getState())){
				articleRel.setState(params.getState());
				articleRel.addEditParam(userInfo);
				updateArticleRelList.add(articleRel);
			}
		}
		if(updateArticleRelList.size()>0){
			articleCompanyRelInfoService.updateBatchById(updateArticleRelList);
		}
	}


	private Map<String,ArticleCompanyRelInfo> getArticleRelMap(String companyNo,Set<String> articleNos){
		Map<String,ArticleCompanyRelInfo> data=new HashMap<>();
		if(articleNos==null || articleNos.size()<=0){
			return data;
		}

		List<ArticleCompanyRelInfo> relList = articleCompanyRelInfoService.list(new QueryWrapper<ArticleCompanyRelInfo>()
				.eq("company_no", companyNo)
				.eq("rows_state", EnabledEnum.ENABLED.getCode())
				.in("article_no",articleNos)
		);
		if(!CollectionUtils.isEmpty(relList)){
			relList.forEach(item->{
				data.put(item.getArticleNo(),item);
			});
		}

		return data;
	}

	@Override
	public IPage<ArticleModel> queryPlatformArticle(PlatformArticleQuery4PageParam params, LoginSimpleUserInfo userInfo) {
		IPage<ArticleInfo> page = articleInfoService.page(new Page<>(params.getPage(), params.getRows()),
			new QueryWrapper<ArticleInfo>()
						.like(StringUtils.hasText(params.getTag()), "tags", "," + params.getTag() + ",")
						.like(StringUtils.hasText(params.getTitle()), "title", params.getTitle())
						.eq("rows_state", BaseConstant.EnabledEnum.ENABLED.getCode())
						.orderByDesc("edt")
		);
		if(page==null || CollectionUtils.isEmpty(page.getRecords())){
			return null;
		}
		Set<String> articleNos=new HashSet<>();
		page.getRecords().forEach(item->{
			articleNos.add(item.getArticleNo());
		});
		Map<String,ArticleCompanyRelInfo>  relInfoMap = this.getArticleRelMap(userInfo.getCompanyNo(),articleNos);
		IPage<ArticleModel> data=page.convert(new Function<ArticleInfo, ArticleModel>() {
			@Override
			public ArticleModel apply(ArticleInfo articleInfo) {
				return  ArticleConvertUtils.getArticleModel(articleInfo,
						relInfoMap.get(articleInfo.getArticleNo()),
						params.getIsDetail());
			}
		});
		return data;
	}

	@Override
	public IPage<ArticleModel> queryArticle(ArticleMgrQuery4PageParam params, LoginSimpleUserInfo userInfo) {
		if (StringUtils.hasText(params.getCategoryId())) {
			IPage<ArticleModel> page = articleMgrMapper.queryArticleByCategory(new Page<>(params.getPage(), params.getRows()),
					new QueryWrapper<ArticleModel>()
							.eq("t2.company_no", userInfo.getCompanyNo())
							.eq("t3.category_id", params.getCategoryId())
							.eq(StringUtils.hasText(params.getCommentStatus()), "t1.comment_status", params.getCommentStatus())
							.like(StringUtils.hasText(params.getTitle()), "t1.title", params.getTitle())
							.orderByDesc("t1.edt")
			);
			return page;
		} else {
			IPage<ArticleModel> page = articleMgrMapper.queryArticle(new Page<>(params.getPage(), params.getRows()),
					new QueryWrapper<ArticleModel>()
							.eq("t2.company_no", userInfo.getCompanyNo())
							.eq(StringUtils.hasText(params.getCommentStatus()), "t1.comment_status", params.getCommentStatus())
							.like(StringUtils.hasText(params.getTitle()), "t1.title", params.getTitle())
							.orderByDesc("t1.edt")
			);
			return page;
		}
	}

}
